# -*- coding: utf-8 -*-
from decimal import Decimal
import datetime
from django.db import models
from django.db.models import Q
from model_utils import Choices
from sti.models import PolymorphicModel
from abs_models.models import RealTimeFramedModel

#class InfoClubePartida(models.Model):
#    "representa os dados de um clube em uma partida"
#    clube = models.ForeignKey('clubes.Clube' , related_name='info_partidas')
#    gols = models.IntegerField(u'Gols', blank=True, null=True)
#    
#    class Meta:
#        app_label = 'campeonatos'
#        
#    def __unicode__(self):
#        return "info: %s" % clube.nome


class Partida(RealTimeFramedModel):
    "Representa uma partida de uma rodada"
    estadio = models.ForeignKey('estadios.Estadio', related_name='partidas')
    #tempos
    pagantes = models.IntegerField(u'Pagantes', null=True, blank=True)
    renda = models.DecimalField(u'Renda', max_digits=10, decimal_places=2, default=Decimal("0"), null=True, blank=True)
    
    clube_mandante = models.ForeignKey('clubes.Clube',related_name='partidas_mandante')
    clube_visitante = models.ForeignKey('clubes.Clube',related_name='partidas_visitante') 
    rodada = models.IntegerField(u'Rodada')
    turno = models.IntegerField(u'Turno')
    encerrada = models.BooleanField(u'Encerrada?',default=False)
    
    class Meta:
        app_label = 'campeonatos'
        ordering = ['start','real_start']
#        unique_together = (
#                           ("numero", "turno"),
#                           )
    def __unicode__(self):
        return "%s x %s" % (self.clube_mandante, self.clube_visitante)
    
    @classmethod
    def _geraTurno(cls,n_clubes, sets=None):
        if len(n_clubes) % 2:
            n_clubes.append(None)
        count    = len(n_clubes)
        sets     = sets or (count - 1)
        half     = count / 2
        schedule = []
        for turn in range(sets):
            pairings = []
            for i in range(half):
                pairings.append((n_clubes[i], n_clubes[count-i-1]))
            n_clubes.insert(1, n_clubes.pop())
            schedule.append(pairings)
        return schedule
    
    @classmethod
    def _geraReturno(cls,n_clubes, sets=None):
        if len(n_clubes) % 2:
            n_clubes.append(None)
        count    = len(n_clubes)
        sets     = sets or (count - 1)
        half     = count / 2
        schedule = []
        for turn in range(sets):
            pairings = []
            for i in range(half):
                pairings.append((n_clubes[count-i-1], n_clubes[i]))
            n_clubes.insert(1, n_clubes.pop())
            schedule.append(pairings)
        return schedule
        

        
    @classmethod
    def criar_partidas_tabela(cls,clubes):
        "cria um campeonato usando os clubes passados como parametro"
        turno = cls._geraTurno([clube for clube in clubes])
        returno = cls._geraReturno([clube for clube in clubes])
        print ">>Turno"
        data_partida=datetime.datetime.now()
        for num_rodada in range(0,len(turno)):
            rodada = turno[num_rodada]
            for mandante, visitante in rodada:
                partida = cls(estadio_id=1,clube_mandante=mandante,clube_visitante=visitante,rodada=num_rodada+1,turno=1)
                #coloca uma partida a cada semana.
                data_partida= data_partida + datetime.timedelta(days=1)
                partida.start=data_partida
                partida.end = data_partida + datetime.timedelta(minutes=90)
                print ">>>> %s" % str(partida)
                partida.save()
            
        print ">>Returno"
        for num_rodada in range(0,len(returno)):
            rodada = returno[num_rodada]
            for mandante, visitante in rodada:
                if mandante and visitante:                    
                    partida = cls(estadio_id=1,clube_mandante=mandante,clube_visitante=visitante,rodada=num_rodada+1,turno=2)
                    #coloca uma partida a cada semana.
                    data_partida= data_partida + datetime.timedelta(days=1)
                    partida.start=data_partida
                    partida.end = data_partida + datetime.timedelta(minutes=90)
                    print ">>>> %s" % str(partida)
                    partida.save()
                    
    @classmethod
    def num_rodadas_turno(cls):
        "retorna o numero de clubes que estao participando de alguma partida usado em alguma conta ai"
        
        from clubes.models import Clube
        num_clubes = Clube.objects.filter(partidas_mandante__gte=1).distinct().count()
        num_rodadas_total =  (num_clubes * 2) - 2 if num_clubes % 2 == 0 else num_clubes * 2
        return num_rodadas_total / 2
    
    
    @classmethod
    def get_partidas_rodada_turno(cls, turno):
        "retorna um vetor de rodadas(vetor de partidas) do turno"
        num_rodadas = cls.num_rodadas_turno()
        partidas = [cls.objects.filter(rodada=rodada, turno=turno) for rodada in range(1,num_rodadas+1)]
        return partidas
    
    def iniciar_partida(self):
        "iniciar esse partida"
        for jogador in self.clube_mandante.escalacao:                    
            self.jogadores.create(jogador=jogador,numero=jogador.numero,tempo_entrada=1)
        for jogador in self.clube_visitante.escalacao:                    
            self.jogadores.create(jogador=jogador,numero=jogador.numero,tempo_entrada=1)
        
        self.real_start = datetime.datetime.now()
        self.save()

    
    def gols_mandante(self,contra=False):
        gols = Q(tipo=1,jogador_ativo__in=self.clube_mandante.escalacao,gol_contra=contra)
        return self.infos.filter(gols)
    
    def gols_visitante(self,contra=False):
        gols = Q(tipo=1,jogador_ativo__in=self.clube_visitante.escalacao,gol_contra=contra)
        return self.infos.filter(gols)
    
    @property
    def placar(self):
        gols_mandante = self.gols_mandante().count() + self.gols_visitante(contra=True).count()
        gols_visitante = self.gols_visitante().count() + self.gols_mandante(contra=True).count()
        return gols_mandante, gols_visitante
    
    @property
    def vencedor(self):
        if self.placar[0] > self.placar[1]:
            return self.clube_mandante
        elif self.placar[0] < self.placar[1]:
            return self.clube_visitante
        
        return None
    
        
#        
#    def gols_mandane_contra(self):
#        gols_contra = Q(tipo=1,gol_contra=True) & ~Q(jogador_ativo__in=self.clube_mandante.escalacao)
#        gols = self.infos.filter(gols,Q())
#        n = self.infos.filter(tipo=1,jogador_ativo__in=self.clube_mandante.escalacao,gol_contra=False)
#        n =.infos.filter(tipo=1,gol_contra=True).exclude(jogador_ativo__in=self.clube_mandante.escalacao)
        
        
class JogadorDePartida(models.Model):
    TEMPOS = Choices(
                       (1,'primeiro',u'Primeiro'),
                       (2,'segundo',u'Segundo'),
                    )
    partida = models.ForeignKey(Partida,related_name='jogadores')
    jogador = models.ForeignKey('jogadores.Jogador',related_name='partidas')
    numero = models.SmallIntegerField(u"Numero",null=False,blank=False)
    
    #informacoes sobre quando o jogador entrou na partida(apenas a primeira vez)
    tempo_entrada = models.SmallIntegerField(u"Tempo em Que entrou",blank=True,null=True,choices=TEMPOS)
    minuto_entrada = models.IntegerField(u"Minuto em que Entrou",blank=True,null=True, default=0)
    
    #informacao sobre quando o jogador saiu da partida.
    tempo_saida = models.SmallIntegerField(u"Tempo em Que Saiu",blank=True,null=True,choices=TEMPOS)
    minuto_saida = models.IntegerField(u"Minuto em que Saiu",blank=True,null=True)
    
    class Meta:
        app_label = 'campeonatos'
        
    #sobreescrevendo o validate unique ja que o unique_together nao funciona para
    #restricao de 2 fk juntas
    def clean(self):
        
        if self.tempo_entrada != self.minuto_entrada:
            if self.tempo_entrada==None or self.minuto_entrada==None:
                raise ValidationError(u'Ao informar um minuto de entrada informe também o tempo de entrada.')
            
        if self.tempo_saida != self.minuto_saida:
            if self.tempo_saida==None or self.minuto_saida==None:
                raise ValidationError(u'Ao informar um minuto de saida informe também o tempo de saida.')
            
        q = JogadorDePartida.objects.all()
        if self.pk : q=q.exclude(pk=self.pk)
        
        if q.filter(jogador=self.jogador,partida=self.partida,numero=self.numero).filter(jogador__clube=self.jogador.clube).exists():
            raise ValidationError(u'Jogador já existe com esse numero desse clube nessa partida.')
        
        
class SingleTabledTypeAwareManager(models.Manager):
    
    def __init__(self, tipo=None, *args, **kwargs):
        super(SingleTabledTypeAwareManager, self).__init__(*args, **kwargs)
        self.tipo = tipo
    
    def get_query_set(self):
        #normal_query
        normal_query = super(SingleTabledTypeAwareManager, self).get_query_set()
        
        #if has a type then the normal query will filter by this type
        if self.tipo:
            normal_query = normal_query.filter(tipo=self.tipo)
            
        return normal_query
    
class InfosDePartida(models.Model):
    "a maioria das informacoes tem um tempo e um minuto em que aconteceram"
    
    CARTOES = Choices(
                       (1,'amarelo',u'Amarelo'),
                       (2,'vermelho',u'Vermelho'),
                    )
    
    TEMPOS = Choices(
                       (1,'primeiro',u'Primeiro'),
                       (2,'segundo',u'Segundo'),
                    )
    
    TIPOS = Choices(
                           (1,'gol',u'Gol'),
                           (2,'subs',u'Substituição'),
                           (3,'falta',u'Falta'),
                           )

    tipo = models.SmallIntegerField(choices=TIPOS,default=1)
    
    tempo = models.SmallIntegerField(u"Tempo",choices=TEMPOS, default=TEMPOS.primeiro)
    minuto = models.IntegerField(u"Minuto",blank=False,null=False)
    
    partida = models.ForeignKey(Partida,related_name='infos')
    
    #: Jogador que responsavel por realizar essa informacao. Ex: Gol(jogador_ativo=jogador que fez o gol, passivo=None), Substituição(ativo=Quem sai, passivo=Quem entra)    
    jogador_ativo = models.ForeignKey('jogadores.Jogador',related_name='infos_ativo')
    jogador_passivo = models.ForeignKey('jogadores.Jogador',related_name='infos_passivo',blank=True, null=True)
    
    gol_contra= models.BooleanField(u"Gol Contra?",default=False)
    cartao = models.SmallIntegerField(u"Cartao",choices=CARTOES,blank=True,null=True)

    objects = SingleTabledTypeAwareManager()

    class Meta:
        app_label = 'campeonatos'
        ordering = ['-tempo','-minuto']
        
                
    
class GolDePartida(InfosDePartida):
    "representa um gol de um jogador em uma partida"
    
    objects = SingleTabledTypeAwareManager(1)
    
    
    def __init__(self, *args, **kwargs):        
        super(GolDePartida, self).__init__(*args, **kwargs)
        self.tipo = 1

    class Meta:
        proxy = True
        app_label = 'campeonatos'
        
    def __unicode__(self):
        return "Gol de %s na partida %s" % (self.jogador_ativo, self.partida)
    
class SubstituicaoDePartida(InfosDePartida):
    "representa uma substituicao em uma partida"
    objects = SingleTabledTypeAwareManager(2)
    
    def __init__(self, *args, **kwargs):        
        super(SubstituicaoDePartida, self).__init__(*args, **kwargs)
        self.tipo = 2
        
    class Meta:
        proxy=True
        app_label = 'campeonatos'
        
    def __unicode__(self):
        return "Substituicao %s -> %s na partida %s" % (self.jogador_ativo, self.jogador_passivo, self.partida)
    
class FaltaDePartida(InfosDePartida):
    "representa uma falta em uma partida"
    objects = SingleTabledTypeAwareManager(3)
    
    def __init__(self, *args, **kwargs):        
        super(FaltaDePartida, self).__init__(*args, **kwargs)
        self.tipo = 3
        
    class Meta:
        proxy=True
        app_label = 'campeonatos'
        
    def __unicode__(self):
        return "Falta de %s em %s na partida %s" % (self.jogador_ativo, self.jogador_passivo, self.partida)
    
    